﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.UI;

namespace Nirvana
{
    [AddComponentMenu("Nirvana/UI/Bind/Variable Bind Image")]
    [RequireComponent(typeof(Image))]
    public sealed class UIVariableBindImage : UIVariableBind
    {
        private static Logger logger = LogSystem.GetLogger("UIVariableBindImage");
        [VariableName(UIVariableType.Asset)]
        [SerializeField]
        private string spriteBind;

        [SerializeField]
        [VariableName(UIVariableType.Float)]
        private string fillAmountBind;
        [SerializeField]
        private bool autoFitNativeSize;
        [SerializeField]
        private bool autoDisable = true;
        private Image _image;
        private AssetID _assetid;
        private UIVariable varSprite,varFill;

        private sealed class UIVariableBindImageEvent
        {
            internal AssetID assetid;
            internal UIVariableBindImage _bindimage;
            internal void LoadSprite(Sprite sprite)
            {
                if (null != sprite)
                {
                    Singleton<SpritePool>.Instance.Free(sprite, false);
                }
                if (this._bindimage._image == null)
                {
                    return;
                }
                if (sprite == null)
                {
                    string text = string.Format("Load sprite {0} failed.", this.assetid);
                    Debug.LogError(text, this._bindimage.gameObject);
                }
                if (this._bindimage._assetid.Equals(this.assetid))
                {
                    Singleton<SpritePool>.Instance.SetSprite(this._bindimage._image, sprite);
                    if (this._bindimage.autoFitNativeSize)
                    {
                        this._bindimage._image.SetNativeSize();
                    }
                    this._bindimage.SetDisable(this._bindimage._image);
                }
            }
        }


        private void Awake()
        {
            base.Binds();
            this._image = base.GetComponent<Image>();
            this.SetDisable(this._image);
        }

        protected override void BindVariables()
        {
            Assert.IsNull<UIVariable>(this.varSprite);
            Assert.IsNull<UIVariable>(this.varFill);
            if (!string.IsNullOrEmpty(this.spriteBind))
            {
                this.varSprite = base.FindVariable(this.spriteBind);
                if (this.varSprite == null)
                {
                    UIVariableBindImage.logger.LogWarning("{0} can not find a variable {1}", new object[]
                    {
                        base.name,
                        this.spriteBind
                    });
                }
                else
                {
                    this.varSprite.OnValueInitialized += this.OnValueInitialized;
                    this.varSprite.OnValueChanged += this.OnValueInitialized;
                    this.varSprite.Add(this);
                    this.OnValueInitialized();
                }
            }
            if (!string.IsNullOrEmpty(this.fillAmountBind))
            {
                this.varFill = base.FindVariable(this.fillAmountBind);
                if (this.varFill == null)
                {
                    UIVariableBindImage.logger.LogWarning("{0} can not find a variable {1}", new object[]
                    {
                        base.name,
                        this.spriteBind
                    });
                }
                else
                {
                    this.varFill.OnValueInitialized += this.SetFillAmount;
                    this.varFill.OnValueChanged += this.SetFillAmount;
                    this.varFill.Add(this);
                    this.SetFillAmount();
                }
            }
        }
        protected override void UnbindVariables()
        {
            if (this.varSprite != null)
            {
                this.varSprite.OnValueInitialized -= this.OnValueInitialized;
                this.varSprite.OnValueChanged -= this.OnValueInitialized;
                this.varSprite.Remove(this);
                this.varSprite = null;
            }
            if (this.varFill != null)
            {
                this.varFill.OnValueInitialized -= this.SetFillAmount;
                this.varFill.OnValueChanged -= this.SetFillAmount;
                this.varFill.Remove(this);
                this.varFill = null;
            }
        }

        private void SetDisable(Image img)
        {
            if (this.autoDisable)
            {
                img.enabled = (img.sprite != null);
            }
        }

        private void LoadSpriteAsync(AssetID assetid)
        {
            UIVariableBindImageEvent _event = new UIVariableBindImageEvent();
            _event.assetid = assetid;
            _event._bindimage = this;
            Singleton<SpritePool>.Instance.Load(_event.assetid, _event.LoadSprite, false);
        }

        private void LoadSprite(AssetID assetid)
        {
            Sprite sprite = assetid.LoadObject<Sprite>();
            if (this._assetid.Equals(assetid))
            {
                this._image.sprite = sprite;
                if (this.autoFitNativeSize)
                {
                    this._image.SetNativeSize();
                }
                this.SetDisable(this._image);
            }
        }

        private void StartLoad(AssetID assetid)
        {
            if (this._assetid.Equals(assetid))
            {
                this.SetDisable(this._image);
                return;
            }
            this._assetid = assetid;
            if (assetid.IsEmpty)
            {
                this._image.sprite = null;
                this.SetDisable(this._image);
                return;
            }

            if (Application.isPlaying)
            {
                this.LoadSpriteAsync(assetid);
            }
            else
            {
                this.LoadSprite(assetid);
            }
        }

        private void SetFillAmount()
        {
            if (this._image == null)
            {
                this._image = base.GetComponent<Image>();
            }
            float value = this.varFill.GetFloat();
            this._image.fillAmount = value;
        }

        private  void OnValueInitialized()
        {
            if (this._image == null)
            {
                this._image = base.GetComponent<Image>();
            }
            if (this._image != null)
            {
                AssetID asset = this.varSprite.GetAsset();
                this.StartLoad(asset);
            }
        }

    }
}


